﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace HFUTCourseSimulation.Kernel.Data.LegacyStorage.V1 {

    public class Semester : Storage.IFromLegacy {
        public Semester() {
            this.Courses = new List<CourseItem>();
            StartDate = DateTime.Today;
            WeekCount = 1;
        }

        [JsonProperty("StartDate", Required = Required.Always)]
        [JsonConverter(typeof(CustomDateTimeConverter))]
        public DateTime StartDate { get; set; }
        [JsonProperty("WeekCount", Required = Required.Always)]
        public int WeekCount { get; set; }
        [JsonProperty("Courses", Required = Required.Always)]
        public List<CourseItem> Courses { get; set; }

        public Storage.Semester ToLatest() {
            return new Storage.Semester() {
                StartDate = StartDate,
                WeekCount = WeekCount.ToString(),
                IndexCount = 11.ToString(),
                BreakfastAt = 0.ToString(),
                LunchAt = 4.ToString(),
                DinnerAt = 8.ToString(),
                Courses = Courses.Select((item) => item.ToLatest()).ToList()
            };
        }
    }

    public class CourseItem {
        public CourseItem() {
            BkColor = Colors.LightBlue;
            this.Schedule = new List<ScheduleItem>();
        }

        [JsonProperty("Name", Required = Required.AllowNull)]
        public string Name { get; set; }
        [JsonProperty("Description", Required = Required.AllowNull)]
        public string Description { get; set; }
        [JsonProperty("BkColor", Required = Required.Always)]
        [JsonConverter(typeof(CustomColorConverter))]
        public Color BkColor { get; set; }
        [JsonProperty("Schedule", Required = Required.Always)]
        public List<ScheduleItem> Schedule { get; set; }

        public Storage.Course ToLatest() {
            return new Storage.Course() {
                Name = Name is null ? "" : Name,
                Description = Description is null ? "" : Description,
                Color = new Storage.ColorPair() {
                    Foreground = Colors.Black,
                    Background = BkColor
                },
                Schedules = Schedule.Select((item) => item.ToLatest()).ToList()
            };
        }
    }

    public class ScheduleItem {
        [JsonProperty("Week", Required = Required.Always)]
        public string Week { get; set; }
        [JsonProperty("Day", Required = Required.Always)]
        public string Day { get; set; }
        [JsonProperty("Index", Required = Required.Always)]
        public string Index { get; set; }

        public Storage.Schedule ToLatest() {
            return new Storage.Schedule() {
                Week = Week,
                Day = Day,
                Index = Index
            };
        }
    }

    internal class CustomDateTimeConverter : JsonConverter<DateTime> {
        public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer) {
            if (reader.TokenType == JsonToken.String) {
                var value = reader.Value as string;
                if (DateTime.TryParse(value, out DateTime rv)) {
                    return rv;
                } else {
                    throw new JsonSerializationException($"given string can not be parsed as DateTime: {value}");
                }
            } else {
                throw new JsonSerializationException($"expect a string but got {reader.TokenType}");
            }
        }

        public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer) {
            writer.WriteValue(value.ToString());
        }
    }

    internal class CustomColorConverter : JsonConverter<Color> {
        public override Color ReadJson(JsonReader reader, Type objectType, Color existingValue, bool hasExistingValue, JsonSerializer serializer) {
            if (reader.TokenType == JsonToken.Integer) {
                var argb = Convert.ToInt32(reader.Value);
                // Read color and force set its Alpha to zero.
                var rv = Util.ColorTrans.ToWpfColor(argb);
                rv.A = 255;
                return rv;
            } else {
                throw new JsonSerializationException($"expect a integer but got {reader.TokenType}");
            }
        }

        public override void WriteJson(JsonWriter writer, Color value, JsonSerializer serializer) {
            // Reset its alpha to zero when saving.
            var copied = value;
            copied.A = 255;
            writer.WriteValue(Util.ColorTrans.ToInt(copied));
        }
    }


}
